﻿using System;
using System.Collections.Generic;
using System.Linq;

namespace Demo.Demos.Basic.SumMatrix
{
	[Serializable]
	public class MatrixElement
	{
		#region Properties (1)
		public float Value { get; set; }
		#endregion
	}

	[Serializable]
	public class MatrixRow : List<MatrixElement>
	{
		#region Properties (1)
		public float SumInRow
		{
			get
			{
				return this.Select(i => i.Value).Sum();
			}
		}
		#endregion

		#region Methods (1)

		public void ValidateRow()
		{
			if (SumInRow < 10)
				throw new ApplicationException("Sum in row must be larger then 10.");
		}

		#endregion
	}

	[Serializable]
	public class ColumnDescriptor
	{
		#region Fields (1)
		private SumMatrixViewModel m_Parent = default(SumMatrixViewModel);
		#endregion

		#region Properties (2)
		public int Column { get; set; }
		public SumMatrixViewModel Parent
		{
			get
			{
				return m_Parent;
			}
		}
		#endregion

		#region Constructors (1)
		public ColumnDescriptor(int column, SumMatrixViewModel parent)
			: base()
		{
			if (parent == null) throw new ArgumentNullException("parent");

			this.Column = column;
			this.m_Parent = parent;
		}
		#endregion
	}

	[Serializable]
	public class SumMatrixViewModel
	{
		#region Fields (3)
		List<MatrixRow> m_Matrix = null;

		private int m_NumberOfColumns = default(int);
		private int m_NumberOfRows = default(int);
		#endregion

		#region Properties (5)
		public IEnumerable<ColumnDescriptor> ColumnDescriptors
		{
			get
			{
				List<ColumnDescriptor> columns = new List<ColumnDescriptor>();

				for (int i = 0; i < NumberOfColumns; ++i)
				{
					columns.Add(new ColumnDescriptor(i, this));
				}

				return columns;
			}
		}
		public List<MatrixRow> Matrix
		{
			get
			{
				return m_Matrix;
			}
		}
		public int NumberOfColumns
		{
			get
			{
				return m_NumberOfColumns;
			}
		}
		public int NumberOfRows
		{
			get
			{
				return m_NumberOfRows;
			}
		}
		public float SumAll
		{
			get
			{
				return this.Matrix.SelectMany(i => i).Select(i => i.Value).Sum();
			}
		}
		#endregion

		#region Constructors (1)
		public SumMatrixViewModel()
		{
			m_Matrix = new List<MatrixRow>();

			AddRow();
			AddRow();
			AddColumn();
			AddColumn();

			Random random = new Random();

			Matrix[0][0].Value = random.Next() % 5;
			Matrix[0][1].Value = random.Next() % 5;
			Matrix[1][0].Value = random.Next() % 5;
			Matrix[1][1].Value = random.Next() % 5;
		}
		#endregion

		#region Methods (3)

		public void AddColumn()
		{
			m_NumberOfColumns++;
			for (int i = 0; i < NumberOfRows; ++i)
			{
				Matrix[i].Add(new MatrixElement());
			}
		}

		public void AddRow()
		{
			m_NumberOfRows++;
			MatrixRow row = new MatrixRow();
			for (int i = 0; i < NumberOfColumns; ++i) 
			{
				row.Add(new MatrixElement());
			}

			Matrix.Add(row);
		}

		public void ValidateAll()
		{
			if (SumAll < 50)
			{
				throw new ApplicationException("Sum must be larger then 50.");
			}
		}

		#endregion
	}
}